package com.think.admin.web.controller;

import com.think.admin.annotations.MenuAnnotation;
import com.think.admin.annotations.ResourceAnnotation;
import com.think.admin.cons.AdminCons;
import com.think.admin.enums.CheckArrEnum;
import com.think.admin.model.dto.role.RoleResourceDTO;
import com.think.admin.model.dto.role.RoleResourceTreeDTO;
import com.think.admin.model.dto.user.UserRoleDto;
import com.think.admin.model.param.resource.ResourceParam;
import com.think.admin.model.param.resource.ResourceUpdateParentIdParam;
import com.think.admin.model.query.ResourceQuery;
import com.think.admin.oauth.util.OAuthUtil;
import com.think.admin.web.service.IResourceService;
import com.think.admin.web.service.IRoleResourceService;
import com.think.common.enums.StateEnum;
import com.think.common.param.UpdateBatchParam;
import com.think.common.utils.ResultUtil;
import com.think.common.utils.SysUtils;
import com.think.common.validation.CreateOrUpdate;
import com.think.common.validation.Update;
import com.think.common.web.controller.SuperController;
import com.think.dao.entity.Resource;
import com.think.dao.entity.RoleResource;
import com.think.dao.enums.ResourcePermissionTypeEnum;
import com.think.dao.enums.ResourceTypeEnum;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RedissonClient;
import org.springframework.http.HttpEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 资源
 * </p>
 *
 * @author xwj
 * @date 2019/4/25
 */
@RestController
@RequestMapping(value = "admin/resource")
@RequiredArgsConstructor
@MenuAnnotation(name = "菜单管理", sort = 3, permissionType = ResourcePermissionTypeEnum.PERMISSION)
public class ResourceController extends SuperController {
    private final IResourceService resourceService;
    private final IRoleResourceService roleResourceService;
    private final RedissonClient redissonClient;

    @GetMapping
    @ResourceAnnotation(name = "查看", sort = 1, permissionType = ResourcePermissionTypeEnum.PERMISSION)
    public HttpEntity list(ResourceQuery resourceQuery) {
        return resourceService.selectResource(resourceQuery);
    }

    @PostMapping
    @ResourceAnnotation(name = "新增修改", sort = 2, permissionType = ResourcePermissionTypeEnum.PERMISSION)
    public HttpEntity createOrUpdate(@RequestBody @Validated(CreateOrUpdate.class) ResourceParam resourceParam) {
        return resourceService.createOrUpdate(resourceParam);
    }

    @PostMapping("/batch-delete")
    @ResourceAnnotation(name = "删除", sort = 3, permissionType = ResourcePermissionTypeEnum.PERMISSION)
    public HttpEntity delete(@RequestBody List<String> idList) {
        return resourceService.delete(idList);
    }

    @PutMapping("/batch-updateState")
    @ResourceAnnotation(name = "启用禁用", sort = 4, permissionType = ResourcePermissionTypeEnum.PERMISSION)
    public HttpEntity updateState(@RequestBody @Validated(Update.class) UpdateBatchParam updateBatchParam) {
        return resourceService.updateState(updateBatchParam);
    }

    @PutMapping("/batch-updateParent")
    @ResourceAnnotation(name = "更新上级", sort = 5, permissionType = ResourcePermissionTypeEnum.PERMISSION)
    public HttpEntity updateParent(@RequestBody @Validated(Update.class)
                                           ResourceUpdateParentIdParam resourceUpdateParentIdParam) {
        return resourceService.updateResourceParent(resourceUpdateParentIdParam);
    }

    @PutMapping("/refreshResource")
    @ResourceAnnotation(name = "刷新资源", sort = 6, permissionType = ResourcePermissionTypeEnum.PERMISSION)
    public HttpEntity refreshResource() {
        return resourceService.refreshResource();
    }

    @GetMapping("/{id}")
    @ResourceAnnotation(name = "资源详情", sort = 7, permissionType = ResourcePermissionTypeEnum.LOGIN)
    public HttpEntity get(@PathVariable("id") String id) {
        return resourceService.getResource(id);
    }

    @GetMapping("/pResource")
    @ResourceAnnotation(name = "目录菜单树", sort = 8, permissionType = ResourcePermissionTypeEnum.LOGIN)
    public HttpEntity<List<Resource>> getPResource() {
        return ResultUtil.success(resourceService.lambdaQuery().select(Resource::getId, Resource::getParentId, Resource::getName)
                .in(Resource::getType, ResourceTypeEnum.DIRECTORY, ResourceTypeEnum.MENU)
                .eq(Resource::getState, StateEnum.ENABLE)
                .orderByAsc(Resource::getType, Resource::getSort).list());
    }

    @GetMapping("/all")
    @ResourceAnnotation(name = "目录菜单资源树", sort = 9, permissionType = ResourcePermissionTypeEnum.LOGIN)
    public HttpEntity<List<RoleResourceTreeDTO>> getAllResource(String roleId) {
        // 获取userId
        String userId = OAuthUtil.getUserId();

        // 查询可分配的菜单
        List<Resource> resourceList;
        if (AdminCons.Param.SUPER_ADMIN_ID.equals(userId)) {
            // 管理员，直接从数据库获取资源
            resourceList = resourceService.lambdaQuery()
                    .select(Resource::getId, Resource::getParentId, Resource::getName, Resource::getType)
                    .in(Resource::getPermissionType, ResourcePermissionTypeEnum.PERMISSION)
                    .eq(Resource::getState, StateEnum.ENABLE)
                    .orderByAsc(Resource::getType, Resource::getSort).list();
        } else {
            // 非管理员，从缓存中获取所拥有的权限
            resourceList = new ArrayList<>();
            Map<String, UserRoleDto> userRoleMap = redissonClient.getMap(AdminCons.Redis.USER_ROLE + userId);
            if (SysUtils.isNotEmpty(userRoleMap)) {
                userRoleMap.keySet().forEach(key -> {
                    Map<String, RoleResourceDTO> roleResource = redissonClient.getMap(AdminCons.Redis.ROLE_RESOURCE + key);
                    if (SysUtils.isEmpty(roleResource)) {
                        return;
                    }
                    roleResource.values().forEach(rr -> {
                        if (SysUtils.isEmpty(rr)) {
                            return;
                        }
                        Resource resource = rr.convert(Resource.class);
                        if (resourceList.contains(resource)) {
                            return;
                        }
                        resourceList.add(resource);
                    });
                });
            }
            resourceList.sort(Comparator.comparing(Resource::getSort));
        }

        // 获取传入角色所拥有的菜单
        List<String> haveResourceIdList;
        if (SysUtils.isNotEmpty(roleId)) {
            haveResourceIdList = roleResourceService.lambdaQuery().select(RoleResource::getResourceId).eq(RoleResource::getRoleId, roleId)
                    .list().stream().filter(SysUtils::isNotEmpty).map(RoleResource::getResourceId)
                    .collect(Collectors.toList());
        } else {
            haveResourceIdList = new ArrayList<>();
        }

        //构造返回数据
        List<RoleResourceTreeDTO> roleResourceTreeDTOList = new ArrayList<>();
        resourceList.forEach(resource -> {
            RoleResourceTreeDTO roleResourceTreeDTO = resource.convert(RoleResourceTreeDTO.class);
            if (SysUtils.isNotEmpty(haveResourceIdList) && haveResourceIdList.contains(resource.getId())) {
                roleResourceTreeDTO.setCheckArr(CheckArrEnum.CHECK.getValue().toString());
            } else {
                roleResourceTreeDTO.setCheckArr(CheckArrEnum.NOT.getValue().toString());
            }
            roleResourceTreeDTOList.add(roleResourceTreeDTO);
        });

        // 返回
        return ResultUtil.success(roleResourceTreeDTOList);
    }
}
